#!/usr/bin/python
# encoding: utf-8

import re

class KeyStrokes:
	
	def __init__(self, env):
		self.env = env
		self.localNameAssociationTable = sorted([(localName+" ",keyName.replace("_loc","_key")) for (keyName,localNames) in env["static"].iteritems() for localName in (localNames.split(", ",1)[0] if env["prefs"]["cwKeys_firstOnly"] else localNames.split(", ")) if keyName.startswith("cwKeys_loc")],key=lambda (k,v): -len(k))
		self.rexAssociationTable = [(re.compile(rex+" "),keyName.replace("_find","_repl")) for (keyName,rexes) in env["static"].iteritems() for rex in rexes.split(", ") if keyName.startswith("cwKeys_find")]
		self.modifiers = set(env["static"]["cwKeys_modifiers"].split(", "))
		d1 = dict((k.replace("cwKeys_postFind",""),re.compile(s,re.M|re.U)) for (k,s) in env["static"].iteritems() if k.startswith("cwKeys_postFind"))
		d2 = dict((k.replace("cwKeys_postRepl",""),s) for (k,s) in env["static"].iteritems() if k.startswith("cwKeys_postRepl"))
		self.postProcessSubs = [(d1[k],d2[k]) for k in d1]
		self.modifierQueue = []
	
	def parse(self,text):
		result = []
		text = " ".join(text.split())+ " "
		low = text.lower()
		while text:
			for (rex,keyIdentifier) in self.rexAssociationTable:
				match = rex.match(low)
				if match:
					result.append(match.expand(self.env["static"][keyIdentifier]))
					i = len(match.group(0))
					break
			else:
				for (localName,keyIdentifier) in self.localNameAssociationTable:
					if low.startswith(localName):
						if keyIdentifier in self.modifiers:
							self.modifierQueue.append(self.env["static"][keyIdentifier])
						else:
							result.append(self.getKeyCommand(self.env["static"][keyIdentifier]))
						i = len(localName)
						break
				else:
					i = text.index(" ") + 1
					result.append(self.getStringCommand(text[:i-1]))
			text = text[i:]
			low = low[i:]
		return self.postProcess("\n".join(result))
	
	def decorateWithModifiers(self,string):
		if self.modifierQueue:
			string = self.getModifierDecoration() % string
			self.modifierQueue = []
		return string
	
	def postProcess(self, result):
		for (rex,repl) in self.postProcessSubs:
			while True:
				(result,n) = rex.subn(repl,result)
				if n == 0:
					break
		return result
